package org.wzy.spring.framework.util;

import org.wzy.spring.framework.aop.JdkDynamicAopProxy;

import java.lang.reflect.Field;
import java.lang.reflect.Proxy;

/**
 * 模拟 Spring 同名类实现
 *
 * @author wzy_h
 * @version v_1.0
 * @date 2018/5/28 22:48
 * @since 1.8
 */
public class AopUtils {

    /**
     * 获取被代理之前的对象
     *
     * @param proxiedObject 被代理后的对象
     * @return 若该对象不是被代理后的对象, 则直接返回, 否则返回代理前的原始对象
     * @author wzy_h
     * @date 2018/5/28 22:51
     * @since 1.8
     */
    public static Object getTargetObject(Object proxiedObject) throws Exception {
        if (!isProxyClass(proxiedObject)) {
            return proxiedObject;
        }

        try {
            return getProxyTargetObject(proxiedObject);
        } catch (NoSuchFieldException | IllegalAccessException e) {
            throw new Exception(e);
        }
    }

    private static Object getProxyTargetObject(Object proxiedObject) throws NoSuchFieldException, IllegalAccessException {
        // 获取生成的代理类 com.sun.proxy..ProxyN 的父类 Proxy 中的 InvocationHandler 对象
        Field field = proxiedObject.getClass().getSuperclass().getDeclaredField("h");
        field.setAccessible(true);

        // 因为 JdkDynamicAopProxy 实现了 InvocationHandler 接口, 因此可以直接强转
        JdkDynamicAopProxy jdkDynamicAopProxy = (JdkDynamicAopProxy) field.get(proxiedObject);
        Field targetField = jdkDynamicAopProxy.getClass().getDeclaredField("target");
        targetField.setAccessible(true);
        return targetField.get(jdkDynamicAopProxy);
    }

    private static boolean isProxyClass(Object object) {
        return Proxy.isProxyClass(object.getClass());
    }
}
